class Snake {
  //表示蛇头的元素
  head: HTMLElement;
  // 蛇的身体(包括蛇头)
  bodies: HTMLCollection;
  element: HTMLElement;

  constructor() {
    this.element = document.getElementById("snake")!;
    this.head = document.querySelector("#snake>div") as HTMLElement;
    this.bodies = this.element.getElementsByTagName("div");
  }

  //获取蛇的 坐标（蛇头坐标）
  get X() {
    return this.head.offsetLeft;
  }
  //获取蛇的Y轴坐标
  get Y() {
    return this.head.offsetTop;
  }

  //设置蛇头的坐标
  set X(val: number) {
    // 如果新值和旧值相同，则直接返回，不再修改
    if (this.X === val) {
      return;
    }
    // X的值的合法范围0-290之间
    if (val < 0 || val > 290) {
      //进入判断说明蛇撞墙了,抛出一个异常
      throw new Error("蛇撞墙了！");
    }

    //修改X时，是在修改水平坐标，蛇在左右移动，蛇在向左移动时，不能向右掉头，反之亦然
    if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetLeft === val) {
      console.log("水平方向发生掉头");
      //如果发生了掉头，让蛇反方向继续移动
      if (val > this.X) {
        //新值大于旧值，说明蛇在向右走，此时发生掉头，应该使蛇继续向左走
        val = this.X - 10;
      } else {
        val = this.X + 10;
      }
    }
    //移动身体
    this.moveBody();
    this.head.style.left = val + "px";
    this.checkHeadBody();
  }

  set Y(val: number) {
    // 如果新值和旧值相同，则直接返回，不再修改
    if (this.Y === val) {
      return;
    }
    if (val < 0 || val > 290) {
      //进入判断说明蛇撞墙了,抛出一个异常
      throw new Error("蛇撞墙了！");
    }

    if (this.bodies[1] && (this.bodies[1] as HTMLElement).offsetTop === val) {
      console.log("水平方向发生掉头");
      //如果发生了掉头，让蛇反方向继续移动
      if (val > this.Y) {
        //新值大于旧值，说明蛇在向右走，此时发生掉头，应该使蛇继续向左走
        val = this.Y - 10;
      } else {
        val = this.Y + 10;
      }
    }

    //移动身体
    this.moveBody();
    this.head.style.top = val + "px";
    this.checkHeadBody();
  }

  //蛇增加身体的方法
  addBody() {
    //向element中添加一个div
    this.element.insertAdjacentHTML("beforeend", "<div></div>");
  }

  //添加一个蛇移动身体
  moveBody() {
    // console.log(this.bodies);
    // 将后边的身体设置为前边身体的位置
    // 第四节=第三节的位置 第三节=第二节的位置  第二节=蛇头的位置

    // 遍历获取所有的身体
    for (let i = this.bodies.length - 1; i > 0; i--) {
      //获取前边身体的位置
      let X = (this.bodies[i - 1] as HTMLElement).offsetLeft;
      let Y = (this.bodies[i - 1] as HTMLElement).offsetTop;

      //将值设置到当前身体上
      (this.bodies[i] as HTMLElement).style.left = X + "px";
      (this.bodies[i] as HTMLElement).style.top = Y + "px";
    }
  }

  //检查蛇头是否撞到身体的 方法
  checkHeadBody() {
    //获取所有的身体，检查其是否和蛇头的坐标发生重叠
    for (let i = 1; i < this.bodies.length; i++) {
      let bd = this.bodies[i] as HTMLElement;
      if (this.X === bd.offsetLeft && this.Y === bd.offsetTop) {
        //进入判断说明蛇头撞到了身体，游戏结束
        throw new Error("撞到自己了!");
      }
    }
  }
}
export default Snake;
